﻿using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using WMS.FC.Application.System;
using WMS.FC.Application.WCS.Interface;
using WMS.FC.Domain.DataTransferObject.WCS;
using WMS.FC.Domain.DomainObject.System;
using WMS.FC.Domain.Repository;
using WMS.FC.Domain.Service.Cell.Interface;
using WMS.FC.Domain.Service.Equipment.Interface;
using WMS.FC.Domain.Service.Station.Interface;
using WMS.FC.Domain.Service.Tasks.Interface;
using WMS.FC.Domain.Service.Tray.Interface;
using WMS.FC.Domain.ValueObject.WCS;

namespace WMS.FC.Application.WCS
{
    public class WcsService : ServiceBase, IWcsService
    {
        protected readonly IBindCellService bindCellService;
        protected readonly IChangeEquipmentStateService changeEquipmentStateService;
        protected readonly IChangeTaskStateService changeTaskStateService;
        protected readonly IGetEmptyTrayOutboundTaskService getEmptyTrayOutboundTaskService;
        protected readonly IGetTrayInfoService getTrayInfoService;
        protected readonly IGetTrayTargetStationService getTrayTargetStationService;
        protected readonly IGetInboundTaskService getInboundTaskService;
        protected readonly IUnbindCellService unbindCellService;

        public WcsService(
            ILogger<ServiceBase> logger,
            IOptions<WmsSettings> options,
            IMapper mapper,
            IUnitOfWork unitOfWork,
            IBindCellService bindCellService,
            IUnbindCellService unbindCellService,
            IChangeEquipmentStateService changeEquipmentStateService,
            IChangeTaskStateService changeTaskStateService,
            IGetTrayInfoService getTrayInfoService,
            IGetTrayTargetStationService getTrayTargetStationService,
            IGetInboundTaskService getInboundTaskService,
            IGetEmptyTrayOutboundTaskService getEmptyTrayOutboundTaskService)
            : base(logger, options, mapper, unitOfWork)
        {
            this.bindCellService = bindCellService;
            this.unbindCellService = unbindCellService;
            this.changeEquipmentStateService = changeEquipmentStateService;
            this.changeTaskStateService = changeTaskStateService;
            this.getTrayInfoService = getTrayInfoService;
            this.getTrayTargetStationService = getTrayTargetStationService;
            this.getInboundTaskService = getInboundTaskService;
            this.getEmptyTrayOutboundTaskService = getEmptyTrayOutboundTaskService;
        }

        public async Task<ResponseBase> BindCell(BindCellDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await bindCellService.BindCell(dTO.TrayBarcode, dTO.CellList, "", dTO.UserInfo);
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> ChangeEquipmentState(ChangeEquipmentStateDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await changeEquipmentStateService.ChangeEquipmentState(dTO.EquipmentCode, dTO.EquipmentState, dTO.UserInfo);
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> ChangeTaskState(ChangeTaskStateDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await changeTaskStateService.ChangeTaskState(dTO.TaskCode, dTO.TaskState, dTO.UserInfo);
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> GetEmptyTrayOutbound(GetEmptyTrayOutboundDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await getEmptyTrayOutboundTaskService.GetEmptyTrayOutboundTask(dTO.StationCode, dTO.MaterialCode, "", dTO.UserInfo);
                });

                response = response.TransferResult(result, mapper.Map<TaskVO>);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> GetTrayInfo(GetTrayInfoDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await getTrayInfoService.GetWCSTrayInfo(dTO.TrayBarcode, dTO.UserInfo);
                });

                response = response.TransferResult(result, mapper.Map<WcsTrayVO>);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> GetTrayTargetStation(GetTrayTargetStationDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await getTrayTargetStationService.GetTrayTargetStation(dTO.TrayBarcode1, dTO.TrayBarcode2, dTO.TrayBarcode3, dTO.StationCode, dTO.UserInfo);
                });

                response = response.TransferResult(result, mapper.Map<TargetStationVO>);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> PutTrayInbound(PutTrayInboundDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await getInboundTaskService.GetInboundTask(dTO.TrayBarcode, dTO.StationCode, dTO.UserInfo);
                });

                response = response.TransferResult(result, mapper.Map<TaskVO>);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }

        public async Task<ResponseBase> UnbindCell(UnbindCellDTO dTO)
        {
            var response = new ResponseBase();
            try
            {
                var result = await unitOfWork.UseTranAsync(async () =>
                {
                    return await unbindCellService.UnbindCell(dTO.TrayBarcode, dTO.CellList, dTO.UserInfo);
                });

                response = response.TransferResult(result);
            }
            catch (Exception ex)
            {
                response = response.Exception(ex);
            }

            return response;
        }
    }
}
